#! /usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright (c) Huoty, All rights reserved
# Author: Huoty <sudohuoty@gmail.com>
# CreateTime: 2018-09-20 21:13:01

"""
http://docs.sqlalchemy.org/en/latest/core/metadata.html
http://docs.sqlalchemy.org/en/latest/core/tutorial.html
http://docs.sqlalchemy.org/en/latest/core/dml.html
"""

from __future__ import print_function

import os
from importlib import import_module
import sqlalchemy
import sqlalchemy.orm


class LocalStore(object):

    from sqlalchemy import MetaData, Table, Column, String, Text, Integer, Index

    _metadata = MetaData()

    _KeyValue = Table(
        'kv', _metadata,
        Column("key", String(50), primary_key=True),
        Column("value", Text)
    )

    _List = Table(
        'list', _metadata,
        Column("id", Integer, primary_key=True),
        Column("name", String(50)),
        Column("item", Text)
    )

    _Map = Table(
        'map', _metadata,
        Column("id", Integer, primary_key=True),
        Column("name", String(50)),
        Column("key", String(50)),
        Column("value", Text)
    )

    Index('map_name_key', _Map.name, _Map.key, unique=True)

    def __init__(self):
        storage_path = os.path.join(os.getenv("HOME"), "temp/nosql.sqlite")
        print(storage_path)
        self._engine = sqlalchemy.create_engine('sqlite:///{}'.format(storage_path))
        self._metadata.create_all(self._engine)
        self._session = sqlalchemy.orm.sessionmaker(bind=self._engine)()
        self._commit = self._session.commit

    def flush(self):
        self._session.commit()

    def _select(self, table, columns=None, where=None):
        sqle = import_module("sqlalchemy.sql").select(columns) if columns else table.select()
        if where is not None:
            sqle.where(where)
        return self._session.execute(sqle)

    def _insert(self, table, values):
        if isinstance(values, list):
            self._session.execute(table.insert(), values)
        elif isinstance(values, dict):
            self._session.execute(table.insert().values(**values))
        else:
            raise Exception()

    def _update(self, table, where, values):
        self._session.execute(table.update().where(where).values(**values))

    def set(self, k, v):
        # cls = self._KeyValue
        # o = self._session.query(cls).filter(cls.key == k).first()
        # if o:
        #     o.value = v
        # else:
        #     o = cls(key=k, value=v)
        #     self._session.add(o)
        # self._commit()

        tab = self._KeyValue
        if self._select(tab, where=(tab.c.key == k)).first():
            self._update(tab, where=(tab.c.key == k), values=dict(value=v))
        else:
            self._insert(tab, values=dict(key=k, value=v))

    def get(self, k):
        # cls = self._KeyValue
        # r = self._session.query(cls.value).filter(cls.key == k).first()
        # if r:
        #     return r[0]

        tab = self._KeyValue
        row = self._select(tab, columns=[tab.c.value], where=(tab.c.key == k)).first()
        if row:
            return row[0]

    def hset(self, top, k, v):
        # cls = Map
        # o = None
        #
        # # 优化, fresh = True, 不需要先 query
        # if not self._fresh:
        #     o = self._session.query(cls).filter(cls.name == top, cls.key == k).first()
        #
        # if o is not None:
        #     o.value = v
        # else:
        #     o = cls(name=top, key=k, value=v)
        #     self._session.add(o)
        # self._commit()
        pass

    def hget(self, top, k):
        # cls = Map
        # r = self._session.query(cls.value).filter(cls.name == top, cls.key == k).first()
        # if r:
        #     return r[0]
        pass

    def hgetall(self, top):
        # r = {}
        # for o in self._session.query(Map).filter(Map.name == top).all():
        #     r[o.key] = o.value
        # return r
        pass


if __name__ == "__main__":
    store = LocalStore()
    store.set("test", "hello world")
    print(store.get("test"))
    store.set("test", "你好世界")
    print(store.get("test"))
    store.flush()
    print(store.get("xxx"))
